home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / tpxms.com / TPXMS.DOC < prev    next >
Encoding:
Text File  |  1989-10-06  |  31.0 KB  |  716 lines

  1.  Page  1
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.                                T P X M S  v1.01
  19.  
  20.                         for Turbo Pascal v4.0 and above
  21.  
  22.                      Extended Memory Routines for HIMEM.SYS
  23.  
  24.                               Vernon E. Davis, Jr.
  25.  
  26.                                    10/06/89
  27.  Page 2
  28.  
  29.  
  30.  
  31.  
  32.  
  33.   Index  .................................................  Page  2
  34.   Introduction to the XMS Specification  .................  Page  3
  35.   Introduction to TPXMS.TPU  .............................  Page  4
  36.   Type Declarations in TPXMS.TPU
  37.      Bit32Struct  ........................................  Page  5
  38.      ExtMemMoveStruct  ...................................  Page  5
  39.      EMBHandleStruct  ....................................  Page  6
  40.      UMBSegmentStruct  ...................................  Page  6
  41.   Variable Declarations in TPXMS.TPU
  42.      isXMS  ..............................................  Page  7
  43.      XMSResult  ..........................................  Page  7
  44.      XMSError  ...........................................  Page  7
  45.      XMM_Control  ........................................  Page  7
  46.   High Memory Routines
  47.      Procedure GetMemHMA  ................................  Page  8
  48.      Procedure FreeMemHMA  ...............................  Page  8
  49.   Extended Memory Routines
  50.      Procedure QueryFreeMemXMS  ..........................  Page  9
  51.      Procedure QueryFreeBlockXMS  ........................  Page  9
  52.      Function  AllocExtMemBlockXMS  ......................  Page  9
  53.      Procedure FreeExtMemBlockXMS  .......................  Page  9
  54.      Procedure MoveExtMemBlockXMS  .......................  Page  9
  55.      Function  LockExtMemBlockXMS  .......................  Page 10
  56.      Procedure UnlockExtMemBlockXMS  .....................  Page 10
  57.      Procedure EMBHandleInfoXMS  .........................  Page 10
  58.      Procedure ReallocExtMemBlockXMS  ....................  Page 10
  59.   Upper Memory Routines
  60.      Procedure ReqUpperMemBlockUMB  ......................  Page 11
  61.      Procedure RelUpperMemBlockUMB  ......................  Page 11
  62.   Miscellaneous Routines
  63.      Function  XMSErrorMsg  ..............................  Page 12
  64.      Procedure PokeAddrXMS  ..............................  Page 12
  65.      Function  ExistXMS  .................................  Page 12
  66.      Procedure GetVerHiMem  ..............................  Page 12
  67.      Procedure GetRevHiMem  ..............................  Page 12
  68.      Procedure GlobalEnableA20  ..........................  Page 12
  69.      Procedure GlobalDisableA20  .........................  Page 13
  70.      Procedure LocalEnableA20  ...........................  Page 13
  71.      Procedure LocalDisableA20  ..........................  Page 13
  72.      Procedure QueryA20  .................................  Page 13
  73.  
  74.    Appendix A
  75.      Reading and Writing to the High Memory Area .........  Page 14
  76.    Appendix B
  77.      Reading and Writing with the Extended Memory Manager   Page 15
  78.    Appendix C
  79.      XMS Error Codes  ...................................   Page 16
  80.    Appendix D
  81.      Revision History  ..................................   Page 17
  82.  
  83.  Page  3
  84.  
  85.   INTRODUCTION TO THE XMS SPECIFICATION:
  86.  
  87.      The XMS Specification, which is a Lotus/Intel/Microsoft/AST joint
  88.   venture, lays the groundwork for access to Extended Memory, the memory
  89.   above the 1-Megabyte boundary on AT-Class and above computer systems.
  90.   The heart of this is HIMEM.SYS; a device driver that loads at boot-time
  91.   from CONFIG.SYS and manages the complex task of reading from and writing
  92.   to Extended Memory.
  93.      This is not to be confused with the EMS Specification, which deals with
  94.   Expanded Memory on PC-Class and above computer systems. The EMS set of
  95.   rules govern a paging memory scheme that allow PC's to store large amounts
  96.   of data in EMS Memory without running out of DOS memory.
  97.      The routines of XMS allow access to Extended Memory for storing data
  98.   and, in some cases, actually running code; all from DOS. The problem of
  99.   switching from the Real Mode, which emulates the 8086/8088 processor, to
  100.   the Protected Mode, which allows access to the entire address space, and
  101.   back again is eliminated.
  102.      There are three classes of routines in XMS:
  103.      o  High Memory Area (HMA) routines:
  104.         These allow access to the first 64K of Extended Memory. Data can be
  105.         store here and code can be executed.
  106.      o  Extended Memory Management (XMM) routines:
  107.         These allow access to the entire physical address space of the
  108.         particular processor (80286 machines can access 16 Megabytes and
  109.         80386 machines can access 4 Gigabytes). Only data can be stored
  110.         and retrieved; no code can be executed.
  111.      o  Upper Memory Block (UMB) routines:
  112.         These allow access to the area of memory between 640K and 1-Megabyte.
  113.         Most AT-Class machines come with at least 1024K of RAM.
  114.         NOTE: The HIMEM.SYS version, as of this writing, does not implement
  115.         these routines and little is known how they will react. The Speci-
  116.         fication does spell out how to call the routines, but they will not
  117.         function.
  118.      There are also routines to manipulate the address line A20 for access
  119.   to the first 64K of Extended Memory and routines for determining the
  120.   version and revision number of HIMEM.SYS.
  121.      The XMS Specification, which includes HIMEM.SYS and documentation, can
  122.   be obtained through a computer club or from the Microsoft Systems Forum on
  123.   CompuServe. The Official XMS Specification can be obtained directly from
  124.   Microsoft.
  125.  
  126.  Page  4
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.   INTRODUCTION TO TPXMS.TPU
  138.  
  139.      The TPXMS.PAS source code is a Turbo Pascal v4.0 and above Unit that
  140.   utilizes the routines in HIMEM.SYS. When compiled, all the functions that
  141.   currently defined in the XMS Specification are easily accessable as Pascal
  142.   Procedures and Functions with Inline Machine Language calls to the XMM
  143.   Manager.
  144.  
  145.      Included in this package ( TPXMS.ZIP ):
  146.  
  147.      o  TPXMS.PAS   : the latest source code for TPXMS.TPU.
  148.      o  XMSTEST.PAS : the latest source code for the TPXMS.TPU tests.
  149.      o  TPXMS.DOC   : this documentation.
  150.  
  151.      Every effort has been taken to insure compatibility with both the
  152.   Specification and Turbo Pascal. As the Specification changes, so will
  153.   this package. Any comments about the XMS Specification should be directed
  154.   to Microsoft. Any comments concerning Turbo Pascal should be directed to
  155.   Borland International. Any comments concerning this package should be 
  156.   directed to the author:
  157.  
  158.         Vernon E. Davis, Jr.
  159.         17 Bowen Avenue
  160.         Woodstown, NJ 08098
  161.         CompuServe [71330,2705]
  162.  
  163.    I release this package to the Public Domain. All I am asking for is
  164.    recognition for the amount of time and work that went into creating
  165.    this package.
  166.                       Vernon E. Davis, Jr.   Initial Release: 07/30/89
  167.                           
  168.  Page  5
  169.  
  170.    TYPE DECLARATIONS IN TPXMS.TPU
  171.  
  172. ** Bit32Struct = LongInt;
  173.  
  174.    This is just a reminder that any value stored in this type should be
  175.    treated as an UNSIGNED 32-bit value. Turbo Pascal's LongInt type is a
  176.    SIGNED 32-bit number; however, any constant value assigned to this type
  177.    is stored as an UNSIGNED number.
  178.    Example: 
  179.              Var lnum : LongInt;
  180.  
  181.              lnum := $FFFFFFFF;
  182.              Write(lnum);        ( the output displays -1 )
  183.  
  184.              However, the actual variable is stored as $FFFFFFFF
  185.  
  186.    The LongInt type has a range of -2,147,483,648 to +2,147,483,647. The
  187.    UNSIGNED number would be 4 Gigabytes or the actual address space of the
  188.    80386 processor. Very few people, if any, will need even 2 Gigabytes of
  189.    addressing, so this should not be a problem.
  190.  
  191. ** ExtMemMoveStruct =
  192.    Record
  193.       Length       : Bit32Struct;  Number of bytes to transfer.
  194.       SourceHandle : Word;         The Source Extended Memory Handle or 0.
  195.       SourceOffset : Bit32Struct;  The offset into block in which to start.
  196.       DestHandle   : Word;         The Dest. Extended Memory Handle or 0.
  197.       DestOffset   : Bit32Struct   The offset into block in which to start.
  198.    End;
  199.  
  200.    This structure sets up the movement of data from Conventional Memory to
  201.    Extended and visa-versa. According to the XMS Specifications, the move
  202.    can also occur from within Conventional Memory or Extended Memory. If
  203.    the SourceHandle or DestHandle is equal to zero, then it is considered
  204.    to be a Conventional Memory location, with the Segment:Offset pair placed
  205.    in the SourceOffset or DestOffset variable, respectively. The Extended
  206.    Memory Handle is obtained through the Allocate Function and the offset
  207.    is how far into the Extended Memory Block to start.
  208.    Example:
  209.              ExtMemMove : ExtMemMoveStruct;
  210.              XMSHandle  : Word;
  211.  
  212.              With ExtMemMove Do
  213.              Begin
  214.                 Length       :=      4000;  { move the entire video buffer }
  215.                 SourceHandle :=         0;  { Conventional Memory Handle   }
  216.                 SourceOffset := $B8000000;  { VIDEO = $B800:0000           }
  217.                 DestHandle   := XMSHandle;  { obtained via AllocExtMemXMS  }
  218.                 DestOffset   :=         0   { start at offset 0            }
  219.              End;
  220.  
  221.    When the MoveExtMemXMS Function is called, the contents of the video
  222.    screen would be written to Extended Memory. ( See the program XMSTEST.PAS
  223.    and Appendix B for actual code. )
  224.  
  225.  Page  6
  226.  
  227.    TYPE DECLARATIONS IN TPXMS.TPU ( continued )
  228.  
  229. ** EMBHandleStruct =
  230.    Record
  231.       LockCount   : Byte;  The number of times that the block has been locked.
  232.       FreeHandles : Byte;  The number of remaining Extended Memory Handles.
  233.       BlockLenKB  : Word   The length, in kilobytes, of the current Extended
  234.                            Memory Block. 
  235.    End;
  236.  
  237.    This structure is used by the EMBHandleInfoXMS procedure to extract
  238.    information about a particular Extended Memory Block.
  239.  
  240. ** UMBSegmentStruct =
  241.    Record
  242.       Segment   : Word;    The segment to which the Upper Memory Block has
  243.                            been assigned.
  244.       UMBSizePG : Word     The actual size of the Upper Memory Block in
  245.                            paragraphs (1 paragraph = 16 bytes).
  246.    End;
  247.  
  248.    Please note that this structure is defined, but the functions in the
  249.    current revision of HIMEM.SYS (2.06) does not access the Upper Memory
  250.    Block. All of these functions return $80 (Function not implemented).
  251.  
  252.  Page  7
  253.  
  254.    VARIABLE DECLARATIONS IN TPXMS.TPU
  255.  
  256. ** isXMS       : Boolean;              TRUE if HIMEM.SYS is correctly
  257.                                        installed. NOTE: All Procedures/
  258.                                        Functions in TPXMS.TPU check for isXMS
  259.                                        equal TRUE. If NOT TRUE, XMSResult
  260.                                        equals 0 and XMSError equals $80.
  261.  
  262. ** XMSResult   : Word;                 Equals 1 if the Function called is
  263.                                        successful, else 0. Some of these
  264.                                        functions do not use this as a result;
  265.                                        instead it is used to return a value 
  266.                                        from the Function.
  267.  
  268. ** XMSError    : Byte;                 If XMSResult = 0 and this byte is
  269.                                        greater or equal to $80, an error
  270.                                        has occurred. See the Appendix C
  271.                                        for an explanation of each value.
  272.  
  273. ** XMM_Control : Array[0..1] of Word;  This is the holder of the actual
  274.                                        address of the XMM_Control Function.
  275.                                        The Offset is contained in [0] and
  276.                                        the Segment is contained in [1]. This
  277.                                        is really an internal variable and has
  278.                                        no other use outside the XMS Functions.
  279.  Page  8
  280.  
  281.    HIGH MEMORY ROUTINES
  282.  
  283. ** Procedure GetMemHMA(Word);
  284.    This procedure attempts to allocate the High Memory Area with the Word
  285.    value passed. Check XMSResult = 1 for success. NOTE: If the /HMAMIN=
  286.    parameter is greater than the amount of memory requested, the procedure
  287.    will fail. ( See the XMS Specifications for more detail. ) NOTE: If
  288.    this procedure is called, the FreeMemHMA procedure MUST be called to
  289.    free the HMA before the program terminates or other programs cannot use
  290.    that memory. ( See Appendix A for reading and writing to the HMA. )
  291.  
  292. ** Procedure FreeMemHMA;
  293.    This procedure will attempt to release the High Memory Area. Check
  294.    XMSResult = 1 for success. NOTE: This function MUST be called to free
  295.    up the HMA before the program terminates or other programs will not 
  296.    have access to the memory.
  297.  
  298.  Page  9
  299.  
  300.    EXTENDED MEMORY ROUTINES
  301.  
  302.  
  303. ** Procedure QueryFreeMemXMS;
  304.    This procedure returns the TOTAL amount of free Extended Memory available
  305.    for access. The value is returned in XMSResult in kilobyte increments.
  306.    Example:
  307.  
  308.          QueryFreeMemXMS;
  309.          Write(XMSResult);
  310.          (The screen displays 256, which means there is a total of 256K
  311.           of Extended Memory available for access.)
  312.  
  313. ** Procedure QueryFreeBlockXMS;
  314.    This procedure returns the LARGEST BLOCK of Extended Memory available
  315.    for access. The value is returned in XMSResult in kilobyte increments.
  316.    Example:
  317.  
  318.          QueryFreeBlockXMS;
  319.          Write(XMSResult);
  320.          (The screen displays 64, which means the largest block of Extended
  321.           Memory available is 64K.)
  322.  
  323. ** Function  AllocExtMemBlockXMS(Word) : Word;
  324.    This function attempts to allocate a block of Extended Memory for data
  325.    storage. If XMSResult = 1 (success), then the value returned from the
  326.    function is the Extended Memory Handle to be used in reference to the
  327.    allocated block. The Word value passed to the function is the amount
  328.    of memory to allocate in kilobytes. Remember that the block must be
  329.    released before the program terminates or that block will remain in
  330.    memory and cannot be accessed again. If XMSResult = 0 (failure), do not
  331.    attempt to use the handle. ( See Appendix B for actual code. )
  332.  
  333. ** Procedure FreeExtMemBlockXMS(Word);
  334.    This procedure releases a block of Extended Memory that was previously
  335.    allocated. The Word value passed to the procedure is the Extended Memory
  336.    Handle of the allocated block. This procedure must be called to release
  337.    a previously allocated block before the program terminates or the memory
  338.    that the block resides in is lost. Check XMSResult = 1 for success.
  339.    ( See Appendix B for actual code. )
  340.  
  341. ** Procedure MoveExtMemBlockXMS(Var ExtMemMoveStruct);
  342.    This procedure moves data from Conventional Memory to Extended Memory and
  343.    visa-versa. The structure passed to the procedure contains the data
  344.    length and source/destination addresses. The structure type is defined
  345.    in the TPU Type Declarations. ( See the Type Declarations above. )
  346.    Check XMSResult = 1 for success. ( See Appendix B for actual code. )
  347.  
  348.  Page 10
  349.  
  350.    HIGH MEMORY ROUTINES ( continued )
  351.  
  352. ** Function  LockExtMemBlockXMS(Word) : Bit32Struct;
  353.    This function attempts to lock an allocated Extended Memory Block; that
  354.    is; making the block unmovable. If there are numerous unlocked blocks
  355.    in Extended Memory and one or more of those blocks are released, the XMM 
  356.    Manager moves the other blocks around to create one large free block of
  357.    memory. This function prevents the block in question from being moved
  358.    from its location in memory. The Word value passed is the Extended Memory
  359.    Handle of the allocated block. The Bit32Struct value returned is the
  360.    linear (actual) address of the block. Check XMSResult = 1 for success.
  361.  
  362.    * IMPORTANT *  A block can be locked more than once. The Lock Count,
  363.    which can be obtained with the EMBHandleInfoXMS procedure, is increased
  364.    by one each time the LockExtMemBlockXMS function is called, up to a 
  365.    maximum of 255 times. In order for a block to be released, its Lock Count
  366.    MUST be zero. Use the UnlockExtMemBlockXMS procedure to decrease the Lock
  367.    Count.
  368.  
  369. ** Procedure UnlockExtMemBlockXMS(Word);
  370.    This procedure reduces the Lock Count of a locked Extended Memory Block
  371.    by one. Because a block can be locked more than once, this routine must
  372.    be called until the Lock Count, obtained through the EMBHandleInfoXMS
  373.    procedure, is zero before the block can be released. The Word value
  374.    passed to the procedure is the Extended Memory Handle. Check XMSResult
  375.    = 1 for success.
  376.  
  377. ** Procedure EMBHandleInfoXMS(Word; Var EMBHandleStruct);
  378.    This procedure gathers information about a particular Extended Memory
  379.    Block and about the XMM environment. The Word value passed to the
  380.    procedure is the Extended Memory Handle. The structure passed to the
  381.    procedure will contain the following information after returning from
  382.    the call:
  383.  
  384.       o  The Lock Count: the number of times that this block has been
  385.          locked via the LockExtMemBlockXMS procedure. If this value is
  386.          zero then the block can be successfully released with the
  387.          FreeExtMemBlockXMS procedure.
  388.       o  The Free Handle Count: the number of free Extended Memory Handles
  389.          that are available. If HIMEM.SYS was loaded without the /NUMHANDLES=
  390.          parameter, then there are a total of 32 handles available.
  391.       o  The Block Size: this value, in kilobytes, is the current size of
  392.          the block in question.
  393.  
  394.    Check XMSResult = 1 for success.
  395.  
  396. ** Procedure ReallocExtMemBlockXMS(Word; Word);
  397.    This procedure will attempt to change the current size of the particular
  398.    Extended Memory Block. The first Word value passed to the procedure is
  399.    the Extended Memory Handle. The second Word value passed to the procedure
  400.    is the new size, in kilobytes, of the block.
  401.  
  402.    * NOTE *  As of this writing, this procedure is not functional. It is a
  403.    result of HIMEM.SYS, not the source code. If called, XMSResult will
  404.    contain 0 and the value in XMSError will be $80 (Function not implemented).
  405.    When HIMEM.SYS is updated, this procedure should work as planned and
  406.    the TPXMS.TPU need not be recompiled.
  407.  
  408.  Page 11
  409.  
  410.    UPPER MEMORY ROUTINES
  411.  
  412. ** Procedure ReqUpperMemBlockUMB(Word; Var UMBSegmentStruct);
  413.    This procedure attempts to allocate an Upper Memory Block. The Word value
  414.    passed to the procedure is the amount of memory to allocate in paragraphs
  415.    ( 1 paragraph = 16 bytes ). The structure passed to the procedure will
  416.    contain the following information after returning from the call:
  417.  
  418.       o  The Segment : the segment of the UMB.
  419.       o  The Block Size : the actual size of the UMB in paragraphs.
  420.  
  421.    * NOTE *  As of this writing, this procedure is not functional. It is a
  422.    result of HIMEM.SYS, not the source code. If called, XMSResult will
  423.    contain 0 and the value in XMSError will be $80 (Function not implemented).
  424.    When HIMEM.SYS is updated, this procedure should work as planned and
  425.    the TPXMS.TPU need not be recompiled.
  426.  
  427. ** Procedure RelUpperMemBlockUMB(Word);
  428.    This procedure releases a previously allocated Upper Memory Block. The
  429.    Word value passed to the procedure is the Segment of the UMB.
  430.  
  431.    * NOTE *  As of this writing, this procedure is not functional. It is a
  432.    result of HIMEM.SYS, not the source code. If called, XMSResult will
  433.    contain 0 and the value in XMSError will be $80 (Function not implemented).
  434.    When HIMEM.SYS is updated, this procedure should work as planned and
  435.    the TPXMS.TPU need not be recompiled.
  436.  
  437.  Page 12
  438.  
  439.    MISCELLANEOUS ROUTINES
  440.  
  441. ** Function  XMSErrorMsg : String;
  442.    This function is not part of the XMS Specification, but is provided as
  443.    convienence to the programmer in intrepreting Error Codes returned by
  444.    the XMM_Control Function. A text message is returned based on the value
  445.    in the XMSError byte. Example: If XMSResult = 0 Then Writeln(XMSErrorMsg);
  446.  
  447. ** Procedure PokeAddrXMS(Var Bit32Struct; Word1, Word2);
  448.    This function is not part of the XMS Specification, but is provided as
  449.    convienence to the programmer in assembling a Segment:Offset pair in a
  450.    Bit32Struct ( LongInt ) format. Place the Segment address of a variable
  451.    in Word1 and the Offset of that variable in Word2. Example:
  452.  
  453.    Var
  454.       buffer     : Array[1..4000] of Byte;
  455.       ExtMemMove : ExtMemMoveStruct;
  456.       XMSHandle  : Word;
  457.    Begin
  458.       XMSHandle := AllocExtMemBlockXMS(4);  { Allocate 4KB }
  459.       With ExtMemMove Do
  460.       Begin
  461.          Length       :=      4000;         { Size of buffer }
  462.          SourceHandle :=         0;         { Use Conventional Memory }
  463.  
  464.          PokeAddrXMS(SourceOffset,Seg(buffer),Ofs(buffer));
  465.          { This call properly stores the Segment:Offset pair
  466.            of the buffer in the SourceOffset Variable. }
  467.  
  468.          DestHandle   := XMSHandle;         { Use Extended Memory }
  469.          DestOffset   :=         0          { Start at Offset 0 }
  470.       End;
  471.       MoveExtMemBlockXMS(ExtMemMove)        { Move buffer to Ext. Memory }
  472.    End;
  473.  
  474. ** Function  ExistXMS : Boolean;
  475.    This Function is called once in the TPU and really does not need to be
  476.    called again. It sets the variable isXMS TRUE if HIMEM.SYS is properly
  477.    loaded and loads the XMM_Control array with the address of XMM_Control.
  478.  
  479. ** Procedure GetVerHiMem;
  480.    This procedure retrieves the version number of HIMEM.SYS in XMSResult.
  481.  
  482. ** Procedure GetRevHiMem;
  483.    This procedure retrieves the revision number of HIMEM.SYS in XMSResult.
  484.  
  485. ** Procedure GlobalEnableA20;
  486.    This toggles the address line A20 high so that access to the High Memory
  487.    Area is obtained. THIS PROCEDURE MUST BE CALLED to access the HMA or
  488.    the system will hang when trying to write to it. ( See Appendix A for
  489.    actual code. )  The GlobalDisableA20 procedure MUST be called BEFORE
  490.    releasing the HMA and BEFORE the program terminates. Check XMSResult = 1
  491.    for success.
  492.  
  493.  Page 13
  494.  
  495.    MISCELLANEOUS ROUTINES - Continued
  496.  
  497. ** Procedure GlobalDisableA20;
  498.    This toggles the address line A20 low. This procedure MUST be called 
  499.    BEFORE releasing the HMA and BEFORE the program terminates. Check
  500.    XMSResult = 1 for success.
  501.  
  502. ** Procedure LocalEnableA20;
  503.    This toggles the address line A20 high so that access to the first 64K
  504.    of Extended Memory is obtained. THIS PROCEDURE MUST BE CALLED to access
  505.    the memory or the system will hang when trying to write to it. ( See
  506.    Appendix A for actual code. )  The LocalDisableA20 procedure MUST be
  507.    called BEFORE the program terminates. Check XMSResult = 1 for success.
  508.  
  509.    * IMPORTANT * This procedure allows the bypass of the HMA access routines.
  510.    Therefore, if there is another program, such as a TSR, in the HMA area,
  511.    and Extended Memory is directly written to, that program in the HMA could
  512.    be destroyed. One possible way to check if the HMA is in use would be to
  513.    call the QueryA20 procedure to determine if address line A20 is active.
  514.    Another way would be to attempt to allocate the HMA by calling the
  515.    GetMemHMA procedure. In short, use the LocalEnableA20 procedure at the
  516.    risk of hanging the system.
  517.  
  518. ** Procedure LocalDisableA20;
  519.    This toggles the address line A20 low. This procedure MUST be called 
  520.    BEFORE the program terminates. Check XMSResult = 1 for success.
  521.  
  522. ** Procedure QueryA20;
  523.    This procedure determines the status of address line A20.
  524.    If XMSResult = 1 then A20 is active (enabled).
  525.    If XMSResult = 0 then A20 is inactive (disabled).
  526.  
  527.  Page 14
  528.  
  529. Appendix A - Reading and Writing to the High Memory Area ( HMA )
  530.  
  531.    The HMA can be directly accessed by DOS and Turbo Pascal. The address of
  532.    the HMA officially begins at $FFFF:$0010 and ends at $FFFF:$FFFF, giving
  533.    a total memory capacity of 65520 bytes ( 64K - 16 bytes ). Study the
  534.    following piece of code:
  535.  
  536.    Program HMA_R_W;
  537.    (* 
  538.    NOTE: This program assumes that HIMEM.SYS is properly loaded and that
  539.    there is 64Kbytes free in the HMA area.
  540.    *)
  541.    Uses
  542.       CRT,DOS,TPXMS;
  543.    Var
  544.       vid : Byte Absolute $B800:$0000;
  545.       hma : Byte Absolute $FFFF:$0010;
  546.       i   : Integer;
  547.    Begin
  548.       GetMemHMA($FFFF);          { Reserve all of the HMA }
  549.       GlobalEnableA20;           { Toggle the A20 address line high }
  550.       ClrScr;                    { Clear the screen }
  551.       For i := 1 To 1999 Do
  552.          Write('A');             { Fill the screen with "A" }
  553.       Move(vid,hma,4000);        { Copy the contents of the screen to HMA }
  554.       ClrScr;                    { Clear the screen }
  555.       Move(hma,vid,4000);        { Restore the screen from HMA }
  556.       GlobalDisableA20;          { Toggle the A20 address line low }
  557.       FreeMemHMA                 { Release the HMA }
  558.    End.
  559.  
  560.  
  561.    The HMA can be bypassed by reading and writing to Direct Memory in the
  562.    same fashion using the LocalEnable/DisableA20 procedures. However, any
  563.    program, such as a TSR currently running in the HMA area, could be over-
  564.    written. Use of this method is not recommended unless it is an absolute
  565.    certainty that there is nothing in the HMA.
  566.  
  567.    Program DMA_R_W;
  568.    (*
  569.    NOTE: This program assumes that HIMEM.SYS is properly loaded.
  570.    *)
  571.    Uses
  572.       CRT,DOS,TPXMS;
  573.    Var
  574.       vid : Byte Absolute $B800:$0000;
  575.       dma : Byte Absolute $FFFF:$0010;
  576.       i   : Integer;
  577.    Begin
  578.       LocalEnableA20;            { Toggle the A20 address line high }
  579.       ClrScr;                    { Clear the screen }
  580.       For i := 1 To 1999 Do
  581.          Write('A');             { Fill the screen with "A" }
  582.       Move(vid,dma,4000);        { Copy the contents of the screen to HMA }
  583.       ClrScr;                    { Clear the screen }
  584.       Move(dma,vid,4000);        { Restore the screen from HMA }
  585.       LocalDisableA20            { Toggle the A20 address line low }
  586.    End.
  587.  
  588.  Page 15
  589.  
  590. Appendix B - Reading and Writing with the Extended Memory Manager ( XMM )
  591.  
  592.    The XMM routines provide access to Extended Memory that is transparent
  593.    to the programmer in switching from Real Mode to Protected Mode and back
  594.    again. Study the following piece of code:
  595.  
  596.    Program XMM_R_W;
  597.    (* 
  598.    NOTE: This program assumes that HIMEM.SYS is properly loaded and that
  599.    there is 4Kbytes free in Extended Memory.
  600.    *)
  601.    Uses
  602.       CRT,DOS,TPXMS;
  603.    Var
  604.       XMSHandle   : Word;
  605.       ExtMemMove  : ExtMemMoveStruct;
  606.       i           : Integer;
  607.    Begin
  608.       XMSHandle := AllocExtMemBlockXMS(4);  { Allocate 4 kilobytes }
  609.       With ExtMemMove Do                    { Load the structure }
  610.       Begin
  611.          Length       :=      4000;         { Size of video screen }
  612.          SourceHandle :=         0;         { Use Conventional Memory }
  613.          SourceOffset := $B8000000;         { VIDEO = $B800:$0000 }
  614.          DestHandle   := XMSHandle;         { Extended Memory Handle }
  615.          DestOffset   :=         0          { Offset 0 into the block }
  616.       End;
  617.       ClrScr;                               { Clear the screen }
  618.       For i := 1 To 1999 Do Write('A');     { Fill the screen with "A" }
  619.       MoveExtMemBlockXMS(ExtMemMove);       { Move screen to Ext. Memory }
  620.       ClrScr;                               { Clear the screen }
  621.       With ExtMemMove Do                    { Load the structure }
  622.       Begin
  623.          Length       :=      4000;         { Size of video screen }
  624.          SourceHandle := XMSHandle;         { Extended Memory Handle }
  625.          SourceOffset :=         0;         { Offset 0 into the block }
  626.          DestHandle   :=         0;         { Use Conventional Memory }
  627.          DestOffset   := $B8000000          { VIDEO = $B800:$0000 }
  628.       End;
  629.       MoveExtMemBlockXMS(ExtMemMove);       { Restore screen from Ext. Mem. }
  630.       FreeExtMemBlockXMS(XMSHandle)         { Release Extended Memory Block }
  631.    End.
  632.  
  633.  Page 16
  634.  
  635. Appendix C - XMS ERROR CODES
  636.  
  637.    If XMSResult = 0 and XMSError is greater than or equal to $80 then
  638.    an error has occurred. The following codes are valid as of this
  639.    writing:
  640.  
  641.    $80 : XMS Function not implemented
  642.    $81 : VDISK detected
  643.    $82 : A20 Error
  644.    $8E : General Driver Error
  645.    $8F : Unrecoverable Driver Error
  646.    $90 : HMA does not exist
  647.    $91 : HMA in use by another process
  648.    $92 : Memory requested less than /HMAMIN= parameter
  649.    $93 : HMA not allocated
  650.    $94 : A20 is enabled
  651.    $A0 : All of Extended Memory is allocated
  652.    $A1 : No Extended Memory Handles available
  653.    $A2 : Extended Memory Handle is invalid
  654.    $A3 : Extended Move Structure: Source Handle is invalid
  655.    $A4 : Extended Move Structure: Source Offset is invalid
  656.    $A5 : Extended Move Structure: Destination Handle is invalid
  657.    $A6 : Extended Move Structure: Destination Offset is invalid
  658.    $A7 : Extended Move Structure: Length is invalid
  659.    $A8 : Extended Move Structure: Move has invalid overlap
  660.    $A9 : Parity Error
  661.    $AA : Block is not locked
  662.    $AB : Block is locked
  663.    $AC : Block Lock Count has overflowed
  664.    $AD : Block Lock has failed
  665.    $B0 : A smaller Upper Memory Block is available
  666.    $B1 : No Upper Memory Blocks are available
  667.    $B2 : Upper Memory Block Segment Number is invalid
  668.  Page 17
  669.  
  670. Appendix D - Revision History
  671.  
  672.    Date    Rev.  Description
  673.  --------  ----  -----------------------------------------------------------
  674.  07/30/89  1.00  Initial Release
  675.  10/06/89  1.01  Fix error in MoveExtMemBlockXMS ( need Segment Override ).
  676.                  Add Procedure PokeAddrXMS for Conventional Memory Moves.
  677.  
  678.  
  679.  
  680.  
  681.  
  682.          ----------------end-of-author's-documentation---------------
  683.  
  684.                         Software Library Information:
  685.  
  686.                    This disk copy provided as a service of
  687.  
  688.                         The Public (Software) Library
  689.  
  690.          We are not the authors of this program, nor are we associated
  691.          with the author in any way other than as a distributor of the
  692.          program in accordance with the author's terms of distribution.
  693.  
  694.          Please direct shareware payments and specific questions about
  695.          this program to the author of the program, whose name appears
  696.          elsewhere in  this documentation. If you have trouble getting
  697.          in touch with the author,  we will do whatever we can to help
  698.          you with your questions. All programs have been tested and do
  699.          run.  To report problems,  please use the form that is in the
  700.          file PROBLEM.DOC on many of our disks or in other written for-
  701.          mat with screen printouts, if possible.  The P(s)L cannot de-
  702.          bug programs over the telephone.
  703.  
  704.          Disks in the P(s)L are updated monthly, so if you did not get
  705.          this disk  directly from the P(s)L,  you should be aware that
  706.          the files in this set may no  longer be the current versions.
  707.  
  708.          For a copy of the latest monthly software library newsletter
  709.          and a list of the 2,000+ disks in the library, call or write
  710.  
  711.                         The Public (Software) Library
  712.                               P.O.Box 35705 - F
  713.                            Houston, TX 77235-5705
  714.                                (713) 665-7017
  715.  
  716.